﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YJKRevitCode.ElmentSearchUtility.LinkDocumentSuite;
using YJKView;

namespace FetchDataCompare
{
	public class DocumentManger
	{
		public View CurrentView { get; set; }

		public string CurrentViewName { get; set; }

		public XMLOperator xmlOper { get; set; }

		public ViewType CurrentViewType { get; set; }

		public Document UseDoc { get; set; }

		public List<Autodesk.Revit.DB.View> Views { get; set; }

		public List<Level> Levels { get; set; }

		public bool IfUseCurrentView { get; set; }

		public List<GeoObjectStructBase> LstGeoObjStruct { get; set; }

		public DocumentManger(Document doc, string currentViewName, bool ifUseCurrentView, ViewType viewType)
		{
			this.xmlOper = new XMLOperator();
			this.Views = new List<Autodesk.Revit.DB.View>();
			this.UseDoc = doc;
			this.GetDocViewPlans();
			if (this.Views.Count <= 0)
			{
				throw new Exception();
			}
			this.IfUseCurrentView = ifUseCurrentView;
			this.CurrentViewName = currentViewName;
			this.CurrentView = this.GetViewByName(currentViewName, viewType);
			this.CurrentViewType = viewType;
			this.LstGeoObjStruct = new List<GeoObjectStructBase>();
			this.Levels = new List<Level>();
			this.GetAllLevel();
		}

		private void GetDocViewPlans()
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.UseDoc);
			ViewType[] viewTypes = new ViewType[]
			{
				(ViewType)116,
				(ViewType)1,
				(ViewType)2,
				(ViewType)3,
				(ViewType)117
			};
			IEnumerable<Element> enumerable = from View item in filteredElementCollector.OfClass(typeof(View)).WhereElementIsNotElementType()
			where !(item is View3D) && !item.IsTemplate && viewTypes.Contains(item.ViewType)
			select item;
			foreach (Element element in enumerable)
			{
				View view = element as View;
				if (view != null)
				{
					this.Views.Add(view);
				}
			}
		}

		private View GetViewByName(string viewName, ViewType viewType)
		{
			foreach (View view in this.Views)
			{
				if (view.ViewType == viewType && view.Name == viewName)
				{
					return view;
				}
			}
			return this.Views[0];
		}

		public GeoObjectStructBase CreateGeoStructByElement(Element element, View view)
		{
			return new GeoObjectStructBase(element, view);
		}

		private string GetElementAttribute(Element element)
		{
			string text = "";
			List<string> needCheckAttribute = this.xmlOper.GetNeedCheckAttribute(element.Category.Id.IntegerValue.ToString());
			foreach (string text2 in needCheckAttribute)
			{
				text = text + text2 + ";";
				BuiltInParameter parameterId = (BuiltInParameter)Enum.Parse(typeof(BuiltInParameter), text2);
				string str = element.GetParameter(parameterId).AsValueString();
				text = text + str + ";";
			}
			return text;
		}

		private GeoObjectBase CreateGeoObjectByElement(Element element)
		{
			GeoObjectBase result = null;
			switch (this.GetElementGeoType(element))
			{
			case EGeoObjectType.eBoudingBoxObj:
				result = new BoundingBoxGeoObject(element);
				break;
			case EGeoObjectType.eDimObj:
				result = new DimGeoObject(element);
				break;
			case EGeoObjectType.eTextNoteObj:
				result = new TextNoteGeoObject(element);
				break;
			}
			return result;
		}

		private EGeoObjectType GetElementGeoType(Element element)
		{
			if (element is Dimension)
			{
				return EGeoObjectType.eDimObj;
			}
			if (element is TextNote)
			{
				return EGeoObjectType.eTextNoteObj;
			}
			return EGeoObjectType.eBoudingBoxObj;
		}

		public void GetAllLevel()
		{
			this.Levels = FloorSelectManager.GetSortLevels(this.UseDoc, double.MinValue, double.MaxValue);
		}

		public double GetNearTopLevel(double elevation)
		{
			for (int i = 0; i < this.Levels.Count - 1; i++)
			{
				double elevation2 = this.Levels[i].Elevation;
				double elevation3 = this.Levels[i + 1].Elevation;
				if (elevation < elevation3 && elevation > elevation2)
				{
					return elevation3;
				}
			}
			return elevation + 3.0;
		}

		public bool InitGeoObjDataByDoc()
		{
			bool result;
			try
			{
				if (this.IfUseCurrentView)
				{
					FilteredElementCollectorLinkDocument collector = new FilteredElementCollectorLinkDocument(this.UseDoc);
					this.Init3DGeoObjDataByView(collector, this.CurrentView);
					this.Init2DGeoObjDataByView(this.CurrentView);
				}
				else
				{
					foreach (View view in this.Views)
					{
                        if ((int)view.ViewType == 1)
						{
							this.Init3DGeoObjData(this.UseDoc, view, false);
						}
						this.Init2DGeoObjDataByView(view);
					}
				}
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		public bool Init3DGeoObjData(Document doc, View view, bool isLinkedDoc = false)
		{
			bool result;
			try
			{
				ElementMulticategoryFilter elementMulticategoryFilter = new ElementMulticategoryFilter(this.xmlOper.GetNeedCheckCategory());
				IList<Type> list = new List<Type>();
				IList<Type> list2 = new List<Type>();
				list2 = this.xmlOper.GetNeedCheckClass(ref list);
				ElementMulticlassFilter elementMulticlassFilter = new ElementMulticlassFilter(list2);
				FilteredElementCollector filteredElementCollector;
				if (!isLinkedDoc)
				{
					filteredElementCollector = new FilteredElementCollector(doc, view.Id);
				}
				else
				{
					filteredElementCollector = new FilteredElementCollector(doc);
				}
				IList<Element> list3 = filteredElementCollector.WherePasses(elementMulticategoryFilter).WherePasses(elementMulticlassFilter).WhereElementIsNotElementType().ToElements();
				foreach (Element element in list3)
				{
					GeoObjectStructBase geoObjectStructBase = GeoObjectStructFactory.CreateGeoObjectIns(element, view);
					geoObjectStructBase.UseDoc = this.UseDoc;
					if (!this.LstGeoObjStruct.Contains(geoObjectStructBase))
					{
						this.LstGeoObjStruct.Add(geoObjectStructBase);
					}
				}
				FilteredElementCollector filteredElementCollector2;
				if (!isLinkedDoc)
				{
					filteredElementCollector2 = new FilteredElementCollector(doc, view.Id);
				}
				else
				{
					filteredElementCollector2 = new FilteredElementCollector(doc);
				}
				IEnumerable<Element> enumerable = from item in filteredElementCollector2.WhereElementIsNotElementType().OfCategory(BuiltInCategory.OST_Lines)
				where item.Name == "模型线"
				select item;
				foreach (Element element2 in enumerable)
				{
					GeoObjectStructBase geoObjectStructBase2 = GeoObjectStructFactory.CreateGeoObjectIns(element2, view);
					geoObjectStructBase2.UseDoc = this.UseDoc;
					if (!this.LstGeoObjStruct.Contains(geoObjectStructBase2))
					{
						this.LstGeoObjStruct.Add(geoObjectStructBase2);
					}
				}
				FilteredElementCollector filteredElementCollector3 = new FilteredElementCollector(doc, view.Id);
				if (!isLinkedDoc)
				{
					filteredElementCollector3 = new FilteredElementCollector(doc, view.Id);
				}
				else
				{
					filteredElementCollector3 = new FilteredElementCollector(doc);
				}
				IList<Element> list4 = filteredElementCollector3.OfClass(typeof(RevitLinkInstance)).ToElements();
				if (list4.Count > 0)
				{
					foreach (Element element3 in list4)
					{
						RevitLinkInstance revitLinkInstance = element3 as RevitLinkInstance;
						if (revitLinkInstance != null)
						{
							Document linkDocument = revitLinkInstance.GetLinkDocument();
							if (linkDocument != null)
							{
								this.Init3DGeoObjData(linkDocument, view, true);
							}
						}
					}
				}
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private bool Init3DGeoObjDataByView(FilteredElementCollectorLinkDocument collector, View view)
		{
			ElementMulticategoryFilter filter = new ElementMulticategoryFilter(this.xmlOper.GetNeedCheckCategory());
			collector.WherePass(filter);
			double elevation = this.CurrentView.GenLevel.Elevation;
			double nearTopLevel = this.GetNearTopLevel(this.CurrentView.GenLevel.Elevation);
			BoundingBoxUV outline = this.CurrentView.Outline;
			UV uv = outline.Min * (double)this.CurrentView.Scale;
			UV uv2 = outline.Max * (double)this.CurrentView.Scale;
			Outline outline2 = new Outline(new XYZ(uv.U, uv.V, elevation), new XYZ(uv2.U, uv2.V, nearTopLevel));
			BoundingBoxIntersectsFilter input = new BoundingBoxIntersectsFilter(outline2);
			collector.AddViewLimit(input);
			List<BaseLinkDocumentResultBean> list = collector.WhereElementIsNotElementType().ToBeans();
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in list)
			{
				GeoObjectStructBase item = new GeoObjectStructBase(baseLinkDocumentResultBean.UseElement, view);
				if (!this.LstGeoObjStruct.Contains(item))
				{
					this.LstGeoObjStruct.Add(item);
				}
			}
			return true;
		}

		private bool Init2DGeoObjDataByView(View view)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.UseDoc, view.Id);
			IList<Type> list = new List<Type>();
			new List<Type>();
			this.xmlOper.GetNeedCheckClass(ref list);
			ICollection<BuiltInCategory> needCheckCategory = this.xmlOper.GetNeedCheckCategory();
			ElementMulticlassFilter elementMulticlassFilter = new ElementMulticlassFilter(list);
			ElementMulticategoryFilter elementMulticategoryFilter = new ElementMulticategoryFilter(needCheckCategory);
			IList<Element> list2 = filteredElementCollector.WherePasses(elementMulticategoryFilter).WherePasses(elementMulticlassFilter).ToElements();
			foreach (Element element in list2)
			{
				GeoObjectStructBase geoObjectStructBase = GeoObjectStructFactory.CreateGeoObjectIns(element, view);
				geoObjectStructBase.UseDoc = this.UseDoc;
				if (!this.LstGeoObjStruct.Contains(geoObjectStructBase))
				{
					this.LstGeoObjStruct.Add(geoObjectStructBase);
				}
			}
			FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(this.UseDoc, view.Id);
			IEnumerable<Element> enumerable = from item in filteredElementCollector2.WhereElementIsNotElementType().OfCategory(BuiltInCategory.OST_Lines)
			where item.Name == "详图线"
			select item;
			foreach (Element element2 in enumerable)
			{
				GeoObjectStructBase geoObjectStructBase2 = GeoObjectStructFactory.CreateGeoObjectIns(element2, view);
				geoObjectStructBase2.UseDoc = this.UseDoc;
				if (!this.LstGeoObjStruct.Contains(geoObjectStructBase2))
				{
					this.LstGeoObjStruct.Add(geoObjectStructBase2);
				}
			}
			return true;
		}
	}
}
